# -*- coding: utf-8 -*-
from datetime import datetime
import pandas as pd
from sklearn.metrics import accuracy_score, f1_score, recall_score
from openai import OpenAI
import Api as api
import pandas as pd
import numpy as np
from sklearn.metrics import accuracy_score, f1_score, recall_score
from tqdm import tqdm
import logging
from datetime import datetime

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# 初始化 DeepSeek 客户端
client = OpenAI(api_key="sk-b6ae6c7c2ae74c01ae26d7d8ae7a503e", base_url="https://api.deepseek.com")

# 获取当前时间，格式为 YYYYMMDD_HHMM
current_time = datetime.now().strftime("%Y%m%d_%H%M")



def evaluate_opinion(true_opinion, pred_opinion):
    """
    调用大模型判断两个 opinion 是否意思一致
    :param true_opinion: 真实 opinion
    :param pred_opinion: 模型生成的 opinion
    :return: True 或 False
    """
    prompt = f"""
你需要判断以下两个观点是否表达了相同的意思：
1. 真实观点：{true_opinion}
2. 生成观点：{pred_opinion}

请严格按照以下要求输出结果：
1. 如果两个观点表达了相同的意思，输出 "True"。
2. 如果两个观点表达了不同的意思，输出 "False"。
3. 不要输出任何其他内容，只需输出 "True" 或 "False"。
"""
    try:
        # 调用 DeepSeek API
        response = client.chat.completions.create(
            model="deepseek-chat",
            messages=[
                {"role": "system", "content": "你是一个帮助判断观点是否一致的助手。"},
                {"role": "user", "content": prompt},
            ],
            stream=False
        )
        # 提取返回结果
        result = response.choices[0].message.content.strip()
        return result == "True"
    except Exception as e:
        print(f"调用 DeepSeek API 出错: {e}")
        return False




def calculate_metrics(true_labels, pred_labels):
    """
    计算分类指标（准确率、F1值、召回率）
    :param true_labels: 真实标签
    :param pred_labels: 预测标签
    :return: 准确率, F1值, 召回率
    """
    true_labels = true_labels.tolist() if hasattr(true_labels, 'tolist') else true_labels
    pred_labels = pred_labels.tolist() if hasattr(pred_labels, 'tolist') else pred_labels
    # 过滤掉 None 值
    valid_indices = [i for i, (true, pred) in enumerate(zip(true_labels, pred_labels)) if
                     true is not None and pred is not None]
    true_labels = [true_labels[i] for i in valid_indices]
    pred_labels = [pred_labels[i] for i in valid_indices]

    if not true_labels or not pred_labels:
        logging.warning("没有有效的标签对来计算指标")
        return 0.0, 0.0, 0.0

    # 计算指标
    accuracy = accuracy_score(true_labels, pred_labels)
    f1 = f1_score(true_labels, pred_labels, average='weighted')
    recall = recall_score(true_labels, pred_labels, average='weighted')
    return accuracy, f1, recall


def process_excel(file_path, simple_flag):
    """
    处理 Excel 文件，调用 API 并计算指标
    :param file_path: Excel 文件路径
    :param simple_flag: 是否进行采样
    """
    # 读取 Excel 文件
    df = pd.read_excel(file_path)

    if simple_flag:
        logging.info(f"总样本数: {len(df)}")
        df = df.sample(frac=0.03, random_state=42)  # random_state 保证每次采样结果一致
        logging.info(f"采样样本数: {len(df)}")

    # 初始化结果列
    df['pred_target'] = None
    df['pred_stance'] = None
    df['pred_opinion'] = None
    df['opinion_match'] = None

    # 遍历每一行
    for index, row in tqdm(df.iterrows(), total=len(df), desc="处理中"):
        back = row['background']
        content = row['content']

        try:
            # 调用 API
            target, stance, opinion = api.call_Llama_api_without_example(back, content)

            # 保存结果
            df.at[index, 'pred_target'] = str(target) if target is not None else None
            df.at[index, 'pred_stance'] = str(stance) if stance is not None else None
            df.at[index, 'pred_opinion'] = str(opinion) if opinion is not None else None

            # 判断 opinion 是否一致
            true_opinion = row['opinion']
            df.at[index, 'opinion_match'] = evaluate_opinion(true_opinion, opinion)

        except Exception as e:
            logging.error(f"处理第 {index} 行时出错: {e}")

    # 按主题分组计算指标
    topics = df['topic'].unique()
    overall_target_true = []
    overall_target_pred = []
    overall_stance_true = []
    overall_stance_pred = []
    overall_opinion_match = []

    for topic in topics:
        topic_df = df[df['topic'] == topic]

        # 计算 target 和 stance 的指标
        target_accuracy, target_f1, target_recall = calculate_metrics(topic_df['target'], topic_df['pred_target'])
        stance_accuracy, stance_f1, stance_recall = calculate_metrics(topic_df['stance'], topic_df['pred_stance'])

        # 计算 opinion 的准确率
        opinion_accuracy = topic_df['opinion_match'].mean()

        # 打印每个主题的指标
        logging.info(f"主题: {topic}")
        logging.info(f"Target 指标: 准确率={target_accuracy}, F1值={target_f1}, 召回率={target_recall}")
        logging.info(f"Stance 指标: 准确率={stance_accuracy}, F1值={stance_f1}, 召回率={stance_recall}")
        logging.info(f"Opinion 准确率: {opinion_accuracy}")
        logging.info("-----------------------------")

        # 收集总体数据
        overall_target_true.extend(topic_df['target'])
        overall_target_pred.extend(topic_df['pred_target'])
        overall_stance_true.extend(topic_df['stance'])
        overall_stance_pred.extend(topic_df['pred_stance'])
        overall_opinion_match.extend(topic_df['opinion_match'])

    # 计算总体指标
    overall_target_accuracy, overall_target_f1, overall_target_recall = calculate_metrics(overall_target_true, overall_target_pred)
    overall_stance_accuracy, overall_stance_f1, overall_stance_recall = calculate_metrics(overall_stance_true, overall_stance_pred)
    overall_opinion_accuracy = sum(overall_opinion_match) / len(overall_opinion_match)

    # 打印总体指标
    logging.info("总体指标:")
    logging.info(f"Target 指标: 准确率={overall_target_accuracy}, F1值={overall_target_f1}, 召回率={overall_target_recall}")
    logging.info(f"Stance 指标: 准确率={overall_stance_accuracy}, F1值={overall_stance_f1}, 召回率={overall_stance_recall}")
    logging.info(f"Opinion 准确率: {overall_opinion_accuracy}")

    # 保存结果到新的 Excel 文件
    current_time = datetime.now().strftime("%Y%m%d_%H%M%S")
    output_file_path = file_path.replace('.xlsx', f'_result_{current_time}.xlsx')
    df.to_excel(output_file_path, index=False)
    logging.info(f"结果已保存到 {output_file_path}")


if __name__ == '__main__':
    # 示例
    example = """
    {
      "target": "政府",
      "stance": "支持",
      "opinion": "因为政府采取了有效的措施来控制疫情。"
    }
    """

    # 处理 Excel 文件
    # process_excel_simple('./test_data/test_data.xlsx')
    process_excel('./test_data/test_data.xlsx', False)